package snippets.cse524.activeDates;

import java.util.ArrayList;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public class SuccessionChainBuilder {
	java.util.List<Predecessor> predecessors = new ArrayList<Predecessor>();
	java.util.List<Office> offices = new ArrayList<Office>();
	java.util.List<Successor> successors = new ArrayList<Successor>();

	private interface SuccessionInfoBuilder {
		SuccessionInfo getSuccessionInfo(java.util.Map<String, String> values);
	}

	private static java.util.Map<String, SuccessionInfoBuilder> builders = new java.util.HashMap<String, SuccessionInfoBuilder>();

	private static int getTimes(Map<String, String> values) {
		String KEY = "rows";

		try {
			return Integer.parseInt(values.get(KEY));
		} catch (Exception _) {
			return 1;
		}
	}

	private static String getString(Map<String, String> values, String key) {
		if (!values.containsKey(key) || StringUtils.isEmpty(values.get(key)))
			return StringUtils.EMPTY;

		try {
			return values.get(key).trim();
		} catch (Exception _) {
			return StringUtils.EMPTY;
		}
	}

	static {
		builders.put("s-new", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				return new Predecessor(WikiPerson.Nobody, getTimes(values));
			}
		});
		builders.put("s-ttl", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				String dateRange = getString(values, "years");
				String begin = StringUtils.EMPTY, end = StringUtils.EMPTY;

				if (dateRange.contains("-")) {
					String parts[] = StringUtils.splitPreserveAllTokens(
							dateRange, "-");
					begin = parts[0];
					end = parts[1];
				} else {
					begin = dateRange;
					end = dateRange;
				}

				return new Office(getString(values, "title"), getTimes(values),
						begin, end);
			}
		});

		builders.put("s-tul", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				String dateRange = getString(values, "years");
				String begin = StringUtils.EMPTY, end = StringUtils.EMPTY;

				if (dateRange.contains("-")) {
					String parts[] = StringUtils.splitPreserveAllTokens(
							dateRange, "-");
					begin = parts[0];
					end = parts[1];
				} else {
					begin = dateRange;
					end = dateRange;
				}

				return new Office(getString(values, "title"), getTimes(values),
						begin, end);
			}
		});

		builders.put("s-aft", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				return new Successor(
						new WikiPerson(getString(values, "after")),
						getTimes(values));
			}
		});
		builders.put("s-bef", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				return new Predecessor(new WikiPerson(getString(values,
						"before")), getTimes(values));
			}
		});
		builders.put("s-vac", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				if (values.containsKey("last") || values.containsKey("unknlast")) {
					return new Predecessor(WikiPerson.Nobody, getTimes(values));
				} else {
					return new Successor(WikiPerson.Nobody, getTimes(values));
				}
			}
		});
		builders.put("s-inc", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				return new Successor(WikiPerson.Nobody, getTimes(values));
			}
		});
		builders.put("s-non", new SuccessionInfoBuilder() {
			@Override
			public SuccessionInfo getSuccessionInfo(Map<String, String> values) {
				return new Successor(WikiPerson.Nobody, getTimes(values));
			}
		});
	}

	private void addSuccessionInfo(SuccessionInfo info) {
		int times = info.getTimes();

		if (info.getClass() == Predecessor.class) {
			while (0 != times--) {
				predecessors.add((Predecessor) info);
			}
		} else if (info.getClass() == Office.class) {
			while (0 != times--) {
				offices.add((Office) info);
			}
		} else if (info.getClass() == Successor.class) {
			while (0 != times--) {
				successors.add((Successor) info);
			}
		} else {
			throw new RuntimeException("Unknow class type: " + info.getClass());
		}
	}

	public void addTag(String tag, java.util.Map<String, String> values) {
		tag = tag.trim();
		
		if (!builders.containsKey(tag)) {
			System.err.println("UNKNOWN TAG: " + tag);
			return;
		} else {
			System.err.println("  KNOWN TAG: " + tag);
		}

		addSuccessionInfo(builders.get(tag).getSuccessionInfo(values));
	}

	public java.util.List<SuccessionChain> getSuccessionChains() {
		if (!(successors.size() == offices.size() && offices.size() == predecessors
				.size())) {
			System.err.println("Mismatch : "
					+ StringUtils.join(new Integer[] { successors.size(),
							offices.size(), predecessors.size() }, ' '));
			return null;
		}

		java.util.List<SuccessionChain> chain = new ArrayList<SuccessionChain>();

		for (int i = 0; i < successors.size(); ++i) {
			chain.add(new SuccessionChain(predecessors.get(i), offices.get(i),
					successors.get(i)));
		}

		return chain;
	}
}
